<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>函数的闭包使用(The use of function closures)</title>
  <!-- 
  JavaScript 函数闭包（Function Closures）总结
  在 JavaScript 中，闭包是一个非常重要的概念，它允许函数访问其外部作用域中的变量。

  1. 基本概念：闭包是指一个函数能够“记住”其外部作用域的变量，即使外部函数已经执行完毕。
    function outerFunction() {
      let outerVariable = '外部变量';
      function innerFunction() {
          console.log(outerVariable); // 访问外部变量
      }
      return innerFunction;
    }
    const closureFunction = outerFunction();
    closureFunction(); // 输出: '外部变量'

  2. 作用域链：闭包可以访问其创建时的作用域链，包括外部函数的变量和全局变量。
    let globalVariable = '全局变量';
    function outerFunction() {
      let outerVariable = '外部变量';

      function innerFunction() {
          console.log(outerVariable); // 访问外部变量
          console.log(globalVariable); // 访问全局变量
      }

      return innerFunction;
    }
    const closureFunction = outerFunction();
    closureFunction(); // 输出: '外部变量', '全局变量'

  3. 私有变量：闭包可以创建私有变量，这些变量无法被外部直接访问，只能通过闭包函数访问。
    function createCounter() {
      let count = 1; // 私有变量
      return {
        increment: function() {
          count++;
          return count;
        },
        decrement: function() {
          count--;
          return count;
        },
        getCount: function() {
          return count;
        }
      };
    }

    const counter = createCounter();
    console.log(counter.increment()); // 输出: 2
    console.log(counter.decrement()); // 输出: 0
    console.log(counter.getCount());  // 输出: 2

  4. 延迟执行：闭包可以用于延迟执行某些操作，特别是在异步编程中非常有用。
    function delayedGreeting(name) {
      return function() {
        console.log(`你好, ${name}!`);
      };
    }

    const greetJohn = delayedGreeting('John');
    setTimeout(greetJohn, 1000); // 1秒后输出: '你好, John!'

  5. 常见应用场景：闭包常用于数据封装、事件处理、回调函数和模块模式等。
    // 模块模式
    const Module = (function() {
      let privateVariable = '私有变量';
      return {
        getPrivateVariable: function() {
          return privateVariable;
        }
      };
    })();

    console.log(Module.getPrivateVariable()); // 输出: '私有变量'

    总结表
  | 特性                   | 描述                                   | 示例                                    |
  |------------------------|----------------------------------------|-----------------------------------------|
  | 基本概念               | 函数能够“记住”外部作用域的变量       |  `closureFunction();`                     |
  | 作用域链               | 访问创建时的作用域链                  |  `console.log(outerVariable);`           |
  | 私有变量               | 创建无法被外部访问的变量              |  `count`  在  `createCounter`  中          |
  | 延迟执行               | 在异步编程中用于延迟执行操作          |  `setTimeout(greetJohn, 1000);`          |
  | 常见应用场景           | 数据封装、事件处理、模块模式等        |  `Module.getPrivateVariable();`          |

  通过理解闭包的概念和用法，可以更灵活地处理 JavaScript 中的作用域和变量。
   -->
</head>
<body>

  <script>
    // 1. 闭包的基本概念
    function closureFunction() {
      let outerVariable = '外部变量';
      function innerFunction() {
        console.log(outerVariable);
      }
      return innerFunction;
    }

    const closure = closureFunction();
    closure(); // 输出: '外部变量'

    // 2. 闭包的作用域链
    function outerFunction() {
      let outerVariable = '外部变量';
      function innerFunction() {
        console.log(outerVariable);
      }
      return innerFunction;
    }

    const scopeChain = outerFunction();
    scopeChain(); // 输出: '外部变量'

    // 3. 闭包的私有变量
    let count = 1;
    function createCounter() {
      let sum = 1 // 私有变量
      return {
        increment: function() {
          count++;
          sum++;
          return { count, sum };
        },
        getCount: function() {
          return { count, sum };
        },
        decrement: function() {
          count--;
          sum--;
          return { count, sum };
        }
      };
    }

    const counter = createCounter();
    const {count: count1, sum: sum1} = counter.increment()
    const {count: count2, sum: sum2} = counter.getCount()
    const {count: count3, sum: sum3} = counter.decrement()

    console.log("increment", count1, sum1); // 输出: 2 2
    console.log("getCount", count2, sum2); // 输出: 2 2
    console.log("decrement", count3, sum3);  // 输出: 1 1
    console.log(count);  // 输出: 1

  </script>
  
</body>
</html>